/*
Christopher Raffaele
02/18/2010
CSC280
Assignement 2 Towers of Hanoi

Stack.h
*/
#pragma once

// templated custom stack class
// simple design
template<typename T>
class Stack{
protected:
	//the blocks of the stack are kept protected so the
	//user need not handle it 
	template<typename T>
	class Node{
	public:
		//data in the node
		T data;
		//pointer to the next node
		Node<T>* next;

		/// <summary>
		/// Creates a new node out of the data
		/// </summary>
		/// <param name="newData">Data to be contained in the node.</param>
		Node(T newData){
			data = newData;
			next = NULL;
		}
	};

	//top of the stack
	Node<T>* top;

	//number of nodes in the stack
	unsigned int size;

public:
	/// <summary>
	/// Create an empty stack
	/// </summary>
	Stack(){
		top = NULL;
		size = 0;
	}

	/// <summary>
	/// Cleans up top pointer, as well as any node left in the stack
	/// </summary>
	~Stack(){
		//delete nodes until the stack is empty
		while(size > 0){
			Pop();
		}

		top = NULL;
		delete top;
	}

	/// <summary>
	/// Returns a bool whether the stack is empty
	/// </summary>
	bool Empty(){
		return !size;
	}

	/// <summary>
	/// Returns an int representing the size of the stack
	/// </summary>
	unsigned int Size(){
		return size;
	}

	/// <summary>
	/// REturns the data from the top node in the stack
	/// </summary>
	T Top(){
		if(size < 1)
			return NULL;

		return top->data;
	}

	/// <summary>
	/// Deletes the top node in the stack
	/// </summary>
	void Pop(){
		Node<T>* temp = top->next;

		//kill link
		top->next = NULL;
		delete top;

		//reset links
		top = temp;

		--size;

		//cleanup temp
		temp = NULL;
		delete temp;
	}

	/// <summary>
	/// Pushes new data noto the stack
	/// </summary>
	/// <param name="data">Data to be placed on the stack.</param>
	void Push(T data){
		//create a new node for new data
		Node<T>* aNode = new Node<T>(data);
		Node<T>* temp = top;

		//setup links
		top = aNode;
		aNode->next = temp;

		++size;

		//cleanup temp
		temp = NULL;
		delete temp;

		//null link to new node
		aNode = NULL;
		delete aNode;
	}
};